﻿using System;
using System.IO;
using System.Collections.Generic;
using System.Linq;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Audio;
using Microsoft.Xna.Framework.Content;
using Microsoft.Xna.Framework.GamerServices;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Input;
using Microsoft.Xna.Framework.Media;

namespace SuperSprintZ
{
    /// <summary>
    /// This is the main type for your game
    /// </summary>
    public class Game1 : Microsoft.Xna.Framework.Game
    {
        GraphicsDeviceManager graphics;
        SpriteBatch spriteBatch;
        public bool bMainmenu = true; //render main menu or not;
        Texture2D autokuva;
        Texture2D hammerkuva1;
        Texture2D hammerkuva2;
        Texture2D hammerkuva3;
        Texture2D hammerkuva4;
        Texture2D hammerkuva5;
        Texture2D hammerkuva6;
        Texture2D hammerkuva7;
        Texture2D hammerkuva8;
        Texture2D hammertanssi1;
        Texture2D hammertanssi2;
        Texture2D hammertanssi3;
        Texture2D hammertanssi4;
        Texture2D hammertanssi5;
        Texture2D hammertanssi6;
        Texture2D hammertanssi7;
        Texture2D hammertanssi8;
        Texture2D kuva;
        Texture2D rata;
        Texture2D ratacolorkey;
        public Player player;
        public Player player2;
        public Color[,] hammervarit1;
        public Color[,] ratavarit;
        public Matrix ratamatriisi;
        Vector2 collisionpoint = new Vector2(0);
        SpriteFont teksti;
        int sekunnit = 0;
        int sadasosat = 0;
        TimeSpan edellinen;
        bool kulunut = true;
        public bool pause = true;
        KeyboardState prevnappis; //the previous state of the keyboard
        TimeSpan pauseaika; //to help keep track of the time even with paused state
        String aika; //the timer to print on the screen
        Menu mainmenu;
        public int lap = 0;
        public int lastlap = 3; //how many laps to drive
        String lapprint;
        Highscore[][] scores;
        int countdowntomenu = 0;
        int startcountdown = 0;
        public bool written = false;
        public bool notstarted = true;
        public int ratanro=0;

        Song kappale;

        public Game1()
        {
            graphics = new GraphicsDeviceManager(this);
            Content.RootDirectory = "Content";
        }

        /// <summary>
        /// Allows the game to perform any initialization it needs to before starting to run.
        /// This is where it can query for any required services and load any non-graphic
        /// related content.  Calling base.Initialize will enumerate through any components
        /// and initialize them as well.
        /// </summary>
        protected override void Initialize()
        {
            // TODO: Add your initialization logic here
            IsMouseVisible = true;
            base.Initialize();
            ratamatriisi = Matrix.Identity; //only works if the screen is resized to the size of the track
            ratamatriisi = Matrix.Invert(ratamatriisi);
            MediaPlayer.Play(kappale);
            MediaPlayer.IsRepeating = true;
            edellinen = new TimeSpan(0, 0, 0);
            pauseaika = new TimeSpan(0, 0, 0);
            prevnappis = Keyboard.GetState();
            player = new Player(this, hammerkuva1, hammerkuva2, hammerkuva3, hammerkuva4, hammerkuva5, hammerkuva6, hammerkuva7, hammerkuva8,autokuva,
                hammertanssi1, hammertanssi2, hammertanssi3, hammertanssi4, hammertanssi5, hammertanssi6, hammertanssi7, hammertanssi8, true);
            player2 = new Player(this, hammerkuva1, hammerkuva2, hammerkuva3, hammerkuva4, hammerkuva5, hammerkuva6, hammerkuva7, hammerkuva8,autokuva,
                hammertanssi1, hammertanssi2, hammertanssi3, hammertanssi4, hammertanssi5, hammertanssi6, hammertanssi7, hammertanssi8, false);
            player.Initialize();
            player2.Initialize();
            int[] radat = new int[3];
            radat[0] = 0;
            radat[1] = 1;
            radat[2] = 2;
            Highscore.setUpHighscoreList(radat);
            scores = Highscore.loadLists();
            aika = "";
            lapprint = "";
            setupMainMenu();
        }

        private void setupMainMenu()
        {
            mainmenu = new Menu(this, teksti, rata.Width, rata.Height);
            mainmenu.addText("Start", 50, 50);
            mainmenu.addText("Choose Track 1", 50, 100);
            mainmenu.addText("Choose Track 2", 50, 150);
         //   mainmenu.addText("Change name for player 1: ", 50, 200);
         //   mainmenu.addText("Choose name for player 2: ", 50, 250);
            mainmenu.addText("Help", 50, 200);
            mainmenu.addText("Exit", 50, 250);
        }


        public void resetTime()
        {
            ResetElapsedTime();
            pauseaika = new TimeSpan(0, 0, 0, 0, 0);
        }

        //makes a 2D color array of a texture (/bitmap)
        public static Color[,] texture2DToColorArray(Texture2D tekstuuri)
        {
            Color[] taulukko = new Color[tekstuuri.Width * tekstuuri.Height];
            tekstuuri.GetData(taulukko);

            Color[,] colors = new Color[tekstuuri.Width, tekstuuri.Height];
            for (int x = 0; x < tekstuuri.Width; x++)
                for (int y = 0; y < tekstuuri.Height; y++)
                    colors[x, y] = taulukko[x + y * tekstuuri.Width];
            return colors;
        }

        /// <summary>
        /// LoadContent will be called once per game and is the place to load
        /// all of your content.
        /// </summary>
        public void reLoad(int ratanro)
        {
            if (ratanro == 0)
            {
                rata = Content.Load<Texture2D>("rata1");
                ratacolorkey = Content.Load<Texture2D>("rata1colorkey");
            }
            if (ratanro == 1)
            {
                rata = Content.Load<Texture2D>("rata2");
                ratacolorkey = Content.Load<Texture2D>("rata2colorkey");
            }
            ratavarit = texture2DToColorArray(ratacolorkey);
            graphics.PreferredBackBufferHeight = rata.Height;
            graphics.PreferredBackBufferWidth = rata.Width;
            //graphics.IsFullScreen = true;
            countdowntomenu = 0;
            startcountdown = 0;
            notstarted = true;
            pause = true;
            graphics.ApplyChanges();
            player.resetPlayer();
            player2.resetPlayer();
        } 
        protected override void LoadContent()
        {
            // Create a new SpriteBatch, which can be used to draw textures.
            spriteBatch = new SpriteBatch(GraphicsDevice);
            autokuva = Content.Load<Texture2D>("auto1");
            hammerkuva1 = Content.Load<Texture2D>("mchammerkuva");
            hammerkuva2 = Content.Load<Texture2D>("mchammerkuva2");
            hammerkuva3 = Content.Load<Texture2D>("mchammerkuva3");
            hammerkuva4 = Content.Load<Texture2D>("mchammerkuva4");
            hammerkuva5 = Content.Load<Texture2D>("mchammerkuva5");
            hammerkuva6 = Content.Load<Texture2D>("mchammerkuva6");
            hammerkuva7 = Content.Load<Texture2D>("mchammerkuva7");
            hammerkuva8 = Content.Load<Texture2D>("mchammerkuva8");
            hammertanssi1 = Content.Load<Texture2D>("hammertanssi1");
            hammertanssi2 = Content.Load<Texture2D>("hammertanssi2");
            hammertanssi3 = Content.Load<Texture2D>("hammertanssi3");
            hammertanssi4 = Content.Load<Texture2D>("hammertanssi4");
            hammertanssi5 = Content.Load<Texture2D>("hammertanssi5");
            hammertanssi6 = Content.Load<Texture2D>("hammertanssi6");
            hammertanssi7 = Content.Load<Texture2D>("hammertanssi7");
            hammertanssi8 = Content.Load<Texture2D>("hammertanssi8");
            rata = Content.Load<Texture2D>("rata1");
            ratacolorkey = Content.Load<Texture2D>("rata1colorkey");
            teksti = Content.Load<SpriteFont>("fontti");
            kappale = Content.Load<Song>("hammertime");
            kuva = hammerkuva1;
            graphics.PreferredBackBufferHeight = rata.Height;
            graphics.PreferredBackBufferWidth = rata.Width;
            //graphics.IsFullScreen = true;
            graphics.ApplyChanges();
            ratavarit = texture2DToColorArray(ratacolorkey);
            hammervarit1 = texture2DToColorArray(hammerkuva1);
        }


        /// <summary>
        /// UnloadContent will be called once per game and is the place to unload
        /// all content.
        /// </summary>
        protected override void UnloadContent()
        {
            // TODO: Unload any non ContentManager content here
        }


        /// <summary>
        /// Allows the game to run logic such as updating the world,
        /// checking for collisions, gathering input, and playing audio.
        /// </summary>
        /// <param name="gameTime">Provides a snapshot of timing values.</param>
        protected override void Update(GameTime gameTime)
        {
            if (bMainmenu)
            {
                mainmenu.Update(gameTime);
            }
            else
            {
                if (!pause && lap != lastlap)
                {
                    pauseaika += gameTime.ElapsedGameTime;
                    sekunnit = pauseaika.Seconds;
                    sadasosat = pauseaika.Milliseconds / 10;
                    this.aika = sekunnit + ":" + sadasosat;
                }
                else
                {
                    if (lap == lastlap)
                    {
                        countdowntomenu++;
                        if (countdowntomenu > 200)
                        {
                            player.resetPlayer();
                            player2.resetPlayer();
                            bMainmenu = true;
                            //back to menu after the game
                        }
                    }
                    else //must be on pause to reach here
                    {
                        if (startcountdown != 200)
                        {
                            pauseaika += gameTime.ElapsedGameTime;
                            sekunnit = pauseaika.Seconds;
                            sadasosat = 0;
                            sekunnit = 3 - sekunnit;
                            this.aika = "Start in: " + sekunnit;
                            startcountdown++;
                        }
                        else
                        { if(notstarted)
                            {
                                notstarted = false;
                                resetTime();
                                pause = false;
                            }
                        }
                    }
                }
                if (gameTime.TotalGameTime.Seconds > edellinen.Seconds + 1 || gameTime.TotalGameTime.Minutes != edellinen.Minutes)
                {
                    kulunut = true;
                }
                if (kulunut)
                {
                    kulunut = false;
                    edellinen = gameTime.TotalGameTime;
                }
                player.Update(gameTime);
                player2.Update(gameTime);
                if (player.hitbox.Intersects(player2.hitbox))
                {
                    player.nopeus = 1;
                    player2.nopeus = 1;
                }
                lapprint = "laps: " + lap + "/" + lastlap;
                if (lastlap <= lap)
                {
                    if (!written)
                    {
                        Highscore.addResult(ratanro, pauseaika.Minutes, pauseaika.Seconds, pauseaika.Milliseconds / 10, "player"); //add highscore to the list if worthy
                    }
                    written = true;
                    lapprint = "";
                    for (int i = 0; i < scores[ratanro].Length; i++)
                    {
                        lapprint += Environment.NewLine + scores[ratanro][i].highscoreToString();
                    }
                }
            }
            base.Update(gameTime);

        }

        /// <summary>
        /// This is called when the game should draw itself.
        /// </summary>
        /// <param name="gameTime">Provides a snapshot of timing values.</param>
        protected override void Draw(GameTime gameTime)
        {
            GraphicsDevice.Clear(Color.CornflowerBlue);
            spriteBatch.Begin();
            if (bMainmenu)
            {
                mainmenu.Draw(gameTime, spriteBatch);
            }
            else
            {
                spriteBatch.Draw(rata, new Vector2(0), GraphicsDevice.PresentationParameters.Bounds, Color.White, 0, new Vector2(0), 1, SpriteEffects.None, 1);
                player.Draw(gameTime, spriteBatch);
                player2.Draw(gameTime, spriteBatch);
                spriteBatch.DrawString(teksti, aika, new Vector2(rata.Width / 2, (rata.Height -50) / 2), Color.Black);
                spriteBatch.DrawString(teksti, lapprint, new Vector2(rata.Width / 2 - teksti.MeasureString("laps: 5/5").X / 2, (rata.Height + teksti.MeasureString("i").Y -50) / 2), Color.Black);
            }
            base.Draw(gameTime);
            spriteBatch.End();
        }
            
    }
}
